﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;

namespace XieCan.AspMVC.Extensions
{
    /// <summary>
    /// JSON操作扩展类
    /// </summary>
    public static class NewtonsoftJsonEx
    {
        /// <summary>
        /// 默认转换设置
        /// <para>日期：yyyy-MM-dd HH:mm:ss</para>
        /// <para>null：直接忽略</para>
        /// <para>属性：驼峰命名法</para>
        /// </summary>
        public static JsonSerializerSettings DefaultSettings => new JsonSerializerSettings()
        {
            //日期类型默认格式化处理
            DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
            DateFormatString = "yyyy-MM-dd HH:mm:ss.ffffff",
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
        };

        /// <summary>
        /// 序列化对象到Json格式的字符串
        /// </summary>
        /// <param name="model">任意一个对象</param>
        /// <param name="format">指定 JsonTextWriter 的格式设置选项</param>
        /// <param name="setting">序列化设置。如果为null，则使用默认设置</param>
        /// <returns>标准的Json格式的字符串</returns>
        public static OperateResult<string> ToJson(this object model, Formatting format = Formatting.None, JsonSerializerSettings setting = null)
        {
            if (model == null)
            {
                return OperateResult<string>.Failed(message: "序列化对象不能为null");
            }

            try
            {
                return OperateResult<string>.Succeeded(JsonConvert.SerializeObject(value: model, formatting: format, settings: setting ?? DefaultSettings));
            }
            catch (Exception ex)
            {
                return OperateResult<string>.Failed(exception: ex);
            }
        }

        /// <summary>
        /// 反序列化Json字符串到指定类型的单个对象或对象集合
        /// <para>Json字符串形式应与T类型形式保持一致。如果Json是集合形式，则T类型也应该是集合形式，否则将转换失败</para>
        /// </summary>
        /// <typeparam name="T">反序列化对象的类型</typeparam>
        /// <param name="json">需要反序列化的Json字符串</param>
        /// <param name="setting">反序列化设置。如果为null，则使用默认设置</param>
        /// <returns>如果转换失败，则返回T类型的默认值</returns>
        public static OperateResult<T> ToModel<T>(this string json, JsonSerializerSettings setting = null)
        {
            if (string.IsNullOrWhiteSpace(value: json))
                return OperateResult<T>.Failed(message: "反序列化的JSON字符串不能为空");

            try
            {
                //如果数据类型一致，都是单个对象或对象集合
                return OperateResult<T>.Succeeded(JsonConvert.DeserializeObject<T>(value: json, settings: setting ?? DefaultSettings));
            }
            catch (Exception ex)
            {
                return OperateResult<T>.Failed(exception: ex);
            }
        }
    }
}

